home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 11
/
Cream of the Crop 11-2.iso
/
extra_2
/
flmgmtcl.zip
/
DIR.CPP
next >
Wrap
C/C++ Source or Header
|
1995-11-02
|
25KB
|
878 lines
// ==========================================================================
// Class Implementation : CDirSpec
// ==========================================================================
// Source file : dir.cpp
// Source : Periphere NV (R.Mortelmans)
// Creation Date : 2nd November. 1995
// Last Modification : 2nd November. 1995
// //////////////////////////////////////////////////////////////////////////
#include "stdafx.h" // standard MFC include
#include "dir.h" // class specification
#include "path.h" // For MakeUnique() and FindLowerDirectory()
#include <direct.h> // For directory functions (getdcwd(), ...)
#include <stdlib.h> // For constant definitions (_MAX_DIR, ...)
#include <dos.h> // For _find_t, _dos_findfirst, ...
#define _A_ALL _A_ARCH | _A_HIDDEN | _A_NORMAL | _A_RDONLY | _A_SYSTEM
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
#include "filelmt.h" // for invalid chars
IMPLEMENT_DYNAMIC(CDirSpec, CObject)
#define new DEBUG_NEW
/////////////////////////////////////////////////////////////////////////////
// Definition of static members
// Data members -------------------------------------------------------------
// protected:
// private:
// CString m_sDrive;
// --- The drive specification consists of a drive letter (capital letter)
// followed be a colon
//CString m_sSubdirectory;
// --- A subdirecory consists of the directory specification, without the drive
// and file specification
// In case of the root directory, it ends in a back slash,
// otherwise it never ends in a back slash
// Member functions ---------------------------------------------------------
// public:
CDirSpec::CDirSpec()
:
m_sDrive(TEXT("")),
m_sSubdirectory(TEXT(""))
{
}
CDirSpec::CDirSpec(const char* pszDirectory)
{
// ... Must be valid pointer
ASSERT(pszDirectory != NULL);
if (!SetDirectory(pszDirectory))
{
TRACE(TEXT("CDirSpec::CDirSpec : An invalid directory (%s) was specified, clearing object\n"),
pszDirectory);
Empty();
}
}
CDirSpec::CDirSpec(const CDirSpec& dirSrc)
:
m_sDrive(dirSrc.m_sDrive),
m_sSubdirectory(dirSrc.m_sSubdirectory)
{
}
BOOL CDirSpec::AppendDirectory(const CDirSpec dirSecond)
{
// The drive spec of dirSecond must be empty or the same as
// that of *this
if (!dirSecond.GetDrive().IsEmpty() && (GetDrive() != dirSecond.GetDrive()))
{
TRACE(TEXT("CDirSpec::AppendDirectory : Illegal drive spec (%s != %s)\n"),
(const char*)GetDrive(), (const char*)dirSecond.GetDrive());
return FALSE;
}
if (dirSecond.GetSubdirectory().IsEmpty())
return TRUE;
if (dirSecond.GetSubdirectory().Left(1) == TEXT("\\"))
{
TRACE(TEXT("CDirSpec::AppendDirectory : Second dir cannot start with back slash (%s)\n"),
dirSecond.GetSubdirectory());
return FALSE;
}
CString sSubdir = GetSubdirectory();
if (!sSubdir.IsEmpty() && (sSubdir.Right(1) != TEXT("\\")))
sSubdir += TEXT("\\");
return SetSubdirectory(sSubdir += dirSecond.GetSubdirectory());
}
const CDirSpec& CDirSpec::operator=(const CDirSpec& dirSrc)
{
m_sDrive = dirSrc.m_sDrive;
m_sSubdirectory = dirSrc.m_sSubdirectory;
return *this;
}
CString CDirSpec::GetDrive() const
{
return m_sDrive;
}
BOOL CDirSpec::SetDrive(const char* pszDrive)
{
// ... Must be valid pointer
ASSERT(pszDrive != NULL);
if (strlen(pszDrive) == 0)
{
m_sDrive = pszDrive;
return TRUE;
}
ASSERT(strlen(pszDrive) != 0);
if ( (('a' <= pszDrive[0]) && (pszDrive[0] <= 'z')) ||
(('A' <= pszDrive[0]) && (pszDrive[0] <= 'Z'))
)
{
m_sDrive = CString(toupper(pszDrive[0])) + ':';
return TRUE;
}
else
{
TRACE(TEXT("CDirSpec::SetDrive : Invalid drive specification (%c)\n"), pszDrive[0]);
return FALSE;
}
}
void CDirSpec::ForceSetDrive(const char* pszDrive)
{
// ... Must be valid pointer
ASSERT(pszDrive != NULL);
if ((0 < strlen(pszDrive)) &&
( (('a' <= pszDrive[0]) && (pszDrive[0] <= 'z')) ||
(('A' <= pszDrive[0]) && (pszDrive[0] <= 'Z'))
)
)
VERIFY(SetDrive(CString(toupper(pszDrive[0])) + TEXT(":")));
else
VERIFY(SetDrive(TEXT("")));
}
CString CDirSpec::GetSubdirectory() const
{
return m_sSubdirectory;
}
BOOL CDirSpec::SetSubdirectory(const char* pszSubdirectory)
{
// ... Must be valid pointer
ASSERT(pszSubdirectory != NULL);
CString sSubdirectory(pszSubdirectory);
// ... Short circuit evaluation
if ( (sSubdirectory.Right(1) != TEXT("\\")) || (sSubdirectory.GetLength() == 1))
{
sSubdirectory.MakeUpper();
if ((int)strcspn(sSubdirectory, INVALID_DIR_CHARS) != sSubdirectory.GetLength())
{
TRACE(TEXT("CFileSpec::SetSubdirectory : Subdirectorye (%s) contains illegal characters\n"), sSubdirectory);
return FALSE;
}
m_sSubdirectory = sSubdirectory;
return TRUE;
}
else
{
TRACE(TEXT("CDirSpec::SetSubdirectory : Only root directory may end in \"\\\", not %s\n"), sSubdirectory);
return FALSE;
}
}
void CDirSpec::ForceSetSubdirectory(const char* pszSubdirectory)
{
// ... Must be valid pointer
ASSERT(pszSubdirectory != NULL);
CString sSubdirectory(pszSubdirectory);
int nIndexWrongChar;
while ((nIndexWrongChar = (int)strcspn(sSubdirectory, INVALID_DIR_CHARS)) != sSubdirectory.GetLength())
{
sSubdirectory = sSubdirectory.Left(nIndexWrongChar) + sSubdirectory.Mid(nIndexWrongChar + 1);
}
if ( (sSubdirectory.Right(1) == TEXT("\\")) && (sSubdirectory.GetLength() != 1))
// Remove trailing back slash
sSubdirectory = sSubdirectory.Mid(0,sSubdirectory.GetLength() - 1);
VERIFY(SetSubdirectory(sSubdirectory));
}
CDirSpec CDirSpec::GetLastSubdirectory() const
{
CDirSpec resultDir;
CString sSubdir;
int nIndex;
resultDir.SetDrive(GetDrive());
sSubdir = GetSubdirectory();
nIndex = sSubdir.ReverseFind('\\');
if (nIndex == -1)
// No back slash found
resultDir.SetSubdirectory(GetSubdirectory());
else
{
ASSERT(0 <= nIndex);
resultDir.SetSubdirectory(sSubdir.Mid(nIndex + 1));
}
return resultDir;
}
void CDirSpec::RemoveLastSubdirectory()
{
int nIndex;
nIndex = m_sSubdirectory.ReverseFind('\\');
if (nIndex != -1)
// Back slash found
{
ASSERT(0 <= nIndex);
if (nIndex != 0)
// Not the root directory
m_sSubdirectory = m_sSubdirectory.Left(nIndex);
else
// The root directory
m_sSubdirectory = TEXT("\\");
}
}
CString CDirSpec::GetDirectory() const
{
return m_sDrive + m_sSubdirectory;
}
BOOL CDirSpec::SetDirectory(const char* pszDirectory)
{
// ... Must be valid pointer
ASSERT(pszDirectory != NULL);
CString sDirectory(pszDirectory);
if (sDirectory.Mid(1,1) == TEXT(":"))
{
if (!SetDrive(sDirectory.Left(2)))
return FALSE;
if (3 <= sDirectory.GetLength())
return SetSubdirectory(sDirectory.Mid(2));
else
return SetSubdirectory(TEXT(""));
}
else
{
return SetDrive(TEXT("")) && SetSubdirectory(sDirectory);
}
}
void CDirSpec::ForceSetDirectory(const char* pszDirectory)
{
// ... Must be valid pointer
ASSERT(pszDirectory != NULL);
if ((0 < strlen(pszDirectory)) && (pszDirectory[1] == ':'))
{
ForceSetDrive(&pszDirectory[0]);
if (3 <= strlen(pszDirectory))
ForceSetSubdirectory(&pszDirectory[2]);
else
ForceSetSubdirectory(TEXT(""));
}
else
{
ForceSetDrive(TEXT(""));
ForceSetSubdirectory(pszDirectory);
}
}
CString CDirSpec::GetFileSystemType()
{
if (m_sDrive.IsEmpty())
{
TRACE(TEXT("CDirSpec::GetFileSystemType : No drive specified, returning empty string\n"));
return TEXT("");
}
#ifdef WIN32
const int nMaxSystemNameLength = 50;
char szSystemName[nMaxSystemNameLength + 1];
BOOL bSuccess;
// ... The Error Mode is temporarily set to SEM_FAILCRITICALERRORS to
// allow failures to immediately return to the calling program.
// This eliminates unwanted dialog boxes that prompt for disks
// to be placed in the drive.
UINT nOldErrorMode = ::SetErrorMode(SEM_FAILCRITICALERRORS);
bSuccess = GetVolumeInformation(m_sDrive + TEXT("\\"), NULL, 0, NULL,
NULL, NULL, szSystemName, nMaxSystemNameLength);
// ... Restore the error code
::SetErrorMode(nOldErrorMode);
if (bSuccess)
return szSystemName;
else
{
TRACE(TEXT("CDirSpec::GetFileSystemType : Could not determine file system, returning empty string\n"));
return TEXT("");
}
#else
// WIN16 cannot distinguish between file systems, so always return "FAT"
return TEXT("FAT");
#endif
}
BOOL CDirSpec::MakeTemp()
{
#ifdef WIN32
CString sTempPath;
BOOL bSuccess = ::GetTempPath(_MAX_PATH, sTempPath.GetBuffer(_MAX_PATH));
sTempPath.ReleaseBuffer();
if (bSuccess)
{
// we'll have to use FORCE... because the path returned
// by WIN32 api ends with a '\'
ForceSetDirectory(sTempPath);
return TRUE;
}
else
return FALSE;
#else
char path_buffer[_MAX_PATH + 1];
char chDriveLetter = 'C';
char* pszSlash = NULL;
// Get temp path
::GetTempFileName(0, // Use the default drive
TEXT("TMP"), // TMP-prefix
1, // Do not try to open and close the file
path_buffer); // Result
// ... Remove the file name (keep only the dir, WITHOUT trailing black slash!)
pszSlash = strrchr(path_buffer, '\\');
if (pszSlash != NULL)
*pszSlash = '\0';
if (*path_buffer != '\0')
{
return SetDirectory(path_buffer);
}
else
{
TRACE(TEXT("CDirSpec::MakeTemp : Could not make temp path, using root of temp drive\n"));
VERIFY(SetDirectory(TEXT("\\")));
return SetDrive(CString(::GetTempDrive(chDriveLetter)));
}
#endif
}
BOOL CDirSpec::MakeUnique()
{
CPathSpec path;
// First convert to file name and at the end convert back to dir
path.SetPath(GetDirectory());
if (path.MakeUnique() && SetDirectory(path.GetPath())) // Short circuit evaluation
return TRUE;
else
{
TRACE(TEXT("CDirSpec::MakeUnique : Could not make unique dir\n"));
return FALSE;
}
}
BOOL CDirSpec::MakeLargestExisting()
{
// Create a temp path spec to make the dir spec absolute
CPathSpec absolutePath;
// .... Dir spec should already be avlid and file spec is valid too,
// so path spec should be valid as well !
VERIFY(absolutePath.SetPath(*this, CFileSpec(TEXT("dummy.tmp"))));
if (!absolutePath.MakeAbsolute())
{
TRACE(TEXT("CDirSpec::MakeLargestExisting : Could not make '%s' absolute, failing\n"),
(const char*)absolutePath.GetPath());
// ... Use root directory (best we can do)
VERIFY(SetDrive(absolutePath.GetDrive()));
VERIFY(SetSubdirectory(TEXT("\\")));
return FALSE;
}
// ... Use direcory part of absoluite path
operator=(absolutePath);
// First check whether the dir spec exists entirely
if (Exists())
return TRUE;
// Now iterate all the subdirectories of this absolute dir spec
// starting from the root, until all subdirs are tried or a non-existing
// subdirectory has been encountered
// E.g. if dir spec = C:\ONE\TWO\THREE then
// then try C:\
// then try C:\ONE
// then try C:\ONE\TWO
// If one of them does not exist, the search is stopped
const char* pszSubdirBegin;
const char* pszPrevSubdirEnd;
const char* pszSubdirEnd;
BOOL bExist = TRUE;
CDirSpec testDir;
pszSubdirBegin = m_sSubdirectory;
pszPrevSubdirEnd = pszSubdirBegin;
pszSubdirEnd = strchr(pszSubdirBegin, '\\');
while (bExist && (pszSubdirEnd != NULL))
{
// ... End the subdir spec BEFORE the terminating back slash
// except when the root (first char is back slash)
if (pszSubdirBegin == pszSubdirEnd)
pszSubdirEnd++;
VERIFY(testDir.SetDrive(GetDrive()));
VERIFY(testDir.SetSubdirectory(CString(pszSubdirBegin, pszSubdirEnd - pszSubdirBegin)));
bExist = testDir.Exists();
if (bExist)
{
// Get next subdir
pszPrevSubdirEnd = pszSubdirEnd;
pszSubdirEnd = strchr(pszSubdirEnd + 1, '\\');
}
}
if (bExist)
{
// All the checked subdirectories exist,
// and we know that the complete dir spec does not exist
ASSERT(!Exists());
ASSERT(pszSubdirEnd == NULL);
ASSERT(pszPrevSubdirEnd != NULL);
VERIFY(SetSubdirectory(CString(pszSubdirBegin, pszPrevSubdirEnd - pszSubdirBegin)));
}
else
{
// A non-existing subdir has been encountered,
// use the last existing sub dir
ASSERT(pszPrevSubdirEnd != NULL);
VERIFY(SetSubdirectory(CString(pszSubdirBegin, pszPrevSubdirEnd - pszSubdirBegin)));
}
// The dir spec must exist now
ASSERT(Exists());
return TRUE;
}
BOOL CDirSpec::Exists() const
{
// Assume that an empty directory or the root directory always exist
// (although CFile::GetStatus("C:\\") return FALSE)
if (GetSubdirectory().IsEmpty() || (GetSubdirectory() == TEXT("\\")))
return TRUE;
CFileStatus fileStatus;
return ( (CFile::GetStatus(GetDirectory(), fileStatus)) &&
(fileStatus.m_attribute & CFile::directory) );
}
BOOL CDirSpec::IsEmpty() const
{
return GetDirectory().IsEmpty();
}
void CDirSpec::Empty()
{
m_sDrive.Empty();
m_sSubdirectory.Empty();
}
BOOL CDirSpec::IsEmptyDir() const
{
CPathSpec filePath;
BOOL bFileFound(FALSE);
BOOL bValid(FALSE);
VERIFY(filePath.SetPath(*this, CFileSpec(TEXT("*.*"))));
#ifdef WIN32
WIN32_FIND_DATA fileData;
HANDLE hFindFile = FindFirstFile(filePath.GetPath(), &fileData);
if (hFindFile != INVALID_HANDLE_VALUE)
bFileFound = TRUE;
// As long a something is found, but is not a good one, keep searching
// ... Ignore non-subdirectories and subdirectories starting with a full steop
while (!bValid && bFileFound)
{
if (fileData.cFileName[0] != __TEXT('.'))
bValid = TRUE;
if (!bValid)
bFileFound = FindNextFile(hFindFile, &fileData);
}
if (hFindFile != INVALID_HANDLE_VALUE)
FindClose(hFindFile);
#else
_find_t fileInfo;
bFileFound = !_dos_findfirst(filePath.GetPath(), _A_SUBDIR | _A_ALL, &fileInfo);
while (!bValid && bFileFound)
{
if ((strcmp(fileInfo.name, TEXT(".")) != 0) && (strcmp(fileInfo.name, TEXT("..")) != 0))
bValid = TRUE;
if (!bValid)
bFileFound = (_dos_findnext(&fileInfo) == 0);
}
#endif
return !bValid;
}
BOOL CDirSpec::DoGetCurrentDir()
{
char pszSubdirectory[_MAX_DIR];
if(_getcwd(pszSubdirectory, _MAX_DIR) != NULL)
{
ASSERT(CString(pszSubdirectory).GetLength() >= 2);
SetDrive(CString(pszSubdirectory).Left(2));
SetSubdirectory(CString(pszSubdirectory).Mid(2));
return TRUE;
}
else
{
TRACE(TEXT("CDirSpec::DoGetCurrentDir : Error occurred while accessing current directory\n"));
return FALSE;
}
}
BOOL CDirSpec::DoSetCurrentDir() const
{
if (!m_sDrive.IsEmpty())
if (_chdrive((int)m_sDrive[0] - 'A' + 1) != 0)
{
TRACE(TEXT("CDirSpec::DoSetCurrentDir : Drive change to %s failed\n"), m_sDrive);
return FALSE;
}
if (!m_sSubdirectory.IsEmpty())
if (_chdir(m_sSubdirectory) != 0)
{
TRACE(TEXT("CDirSpec::DoSetCurrentDir : Directory change to %s failed\n"), m_sSubdirectory);
return FALSE;
}
return TRUE;
}
BOOL CDirSpec::DoMakeNew() const
{
// Do not try to create a directory with an empty name and
// do not try to create the root directory (it already exists)
if (!m_sSubdirectory.IsEmpty() && (m_sSubdirectory != TEXT("\\")))
{
CString sDir = m_sDrive + m_sSubdirectory;
// First try to create all the directories in front of the last back slash
// This is done without error checking, because they may already exist
int nSlashPosition;
int nDeltaSlashPosition;
nDeltaSlashPosition = sDir.Find('\\');
nSlashPosition = nDeltaSlashPosition;
while ( nDeltaSlashPosition != -1)
{
_mkdir(sDir.Left(nSlashPosition));
// ... Only root dir can end in \\ and this case is excluded here by spanning is
ASSERT(sDir.Right(1) != TEXT("\\"));
nDeltaSlashPosition = sDir.Mid(nSlashPosition + 1).Find('\\');
nSlashPosition += nDeltaSlashPosition + 1;
}
// Now try to create the entire directory specification,
// with error checking
if (_mkdir(sDir) != 0)
{
TRACE(TEXT("CDirSpec::DoMakeNew : Directory creation %s failed\n"), sDir);
return FALSE;
}
}
return TRUE;
}
BOOL CDirSpec::DoRemove(BOOL bRecursively /* = FALSE */,
BOOL bAlsoRemoveReadOnly /* = FALSE */) const
{
#ifdef _DEBUG
if (GetSubdirectory() == TEXT("\\"))
{
TRACE(TEXT("CDirSpec::DoRemove : Trying to remove root directory (%s) and all it's subdirectories\n"),
GetSubdirectory());
// Dangerous situation : Give user change to abort or go on (retry)
ASSERT(FALSE);
}
#endif
if (!m_sSubdirectory.IsEmpty())
{
if (bRecursively)
// First remove all underlying directories
{
CDirSpec lowerDir;
lowerDir = FindLowerDirectory();
while (!lowerDir.IsEmpty())
{
if (!lowerDir.DoRemove(bRecursively, bAlsoRemoveReadOnly))
// Could not remove lower directory, abort
return FALSE;
lowerDir = FindLowerDirectory();
}
}
// Remove all the files in the directory
if (!RemoveAllFiles(bAlsoRemoveReadOnly))
{
TRACE(TEXT("CDirSpec::DoRemove : Removal of files failed, cannot remove directory %s\n"), GetDirectory());
return FALSE;
}
// Remove the directory itself
#ifdef WIN32
if (!RemoveDirectory(GetDirectory()))
#else
if (_rmdir(GetDirectory()) != 0)
#endif
{
TRACE(TEXT("CDirSpec::DoRemove : Cannot remove directory : %s\n"), GetDirectory());
return FALSE;
}
}
return TRUE;
}
BOOL CDirSpec::operator==(CDirSpec dirSpec) const
{
return ( (m_sDrive == dirSpec.m_sDrive) &&
(m_sSubdirectory == dirSpec.m_sSubdirectory) );
}
BOOL CDirSpec::operator!=(CDirSpec dirSpec) const
{
return ( (m_sDrive != dirSpec.m_sDrive) ||
(m_sSubdirectory != dirSpec.m_sSubdirectory) );
}
BOOL CDirSpec::operator<=(CDirSpec dirSpec) const
{
return (m_sDrive + m_sSubdirectory <= dirSpec.m_sDrive + dirSpec.m_sSubdirectory);
}
BOOL CDirSpec::operator<(CDirSpec dirSpec) const
{
return (m_sDrive + m_sSubdirectory < dirSpec.m_sDrive + dirSpec.m_sSubdirectory);
}
BOOL CDirSpec::operator>=(CDirSpec dirSpec) const
{
return (m_sDrive + m_sSubdirectory >= dirSpec.m_sDrive + dirSpec.m_sSubdirectory);
}
BOOL CDirSpec::operator>(CDirSpec dirSpec) const
{
return (m_sDrive + m_sSubdirectory > dirSpec.m_sDrive + dirSpec.m_sSubdirectory);
}
#ifdef _DEBUG
void CDirSpec::Dump(CDumpContext& dc) const
{
CObject::Dump(dc);
dc << TEXT("\nm_sDrive : ") << m_sDrive;
dc << TEXT("\nm_sSubdirectory : ") << m_sSubdirectory;
}
void CDirSpec::AssertValid() const
{
CObject::AssertValid();
}
#endif
CDirSpec::~CDirSpec()
{
}
#ifdef WIN32
BOOL CDirSpec::IsChildDir(LPWIN32_FIND_DATA lpFindFileData) const
// --- In :
// --- Out :
// --- Returns : if lpFindFileData contains a subdir...
// --- Effect :
{
return (
(lpFindFileData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
(lpFindFileData->cFileName[0] != __TEXT('.')));
}
#endif
// protected:
CDirSpec CDirSpec::FindLowerDirectory() const
// --- In :
// --- Out :
// --- Returns : A directory that is a subdirectory of this dir spec
// --- Effect :
{
CDirSpec lowerDir;
CPathSpec searchPath;
VERIFY(searchPath.SetPath(*this, CFileSpec(TEXT("*.*"))));
BOOL bDirFound(FALSE);
BOOL bFileFound(TRUE);
#ifdef WIN32
WIN32_FIND_DATA fileData;
HANDLE hFindFile = FindFirstFile(searchPath.GetPath(), &fileData);
if (hFindFile != INVALID_HANDLE_VALUE)
bFileFound = TRUE;
// As long a something is found, but is not a good one, keep searching
// ... Ignore non-subdirectories and subdirectories starting with a full steop
while (!bDirFound && bFileFound)
{
bDirFound = IsChildDir(&fileData);
if (!bDirFound)
bFileFound = FindNextFile(hFindFile, &fileData);
}
if (hFindFile != INVALID_HANDLE_VALUE)
FindClose(hFindFile);
if (bDirFound)
{
lowerDir = *this;
VERIFY(lowerDir.AppendDirectory(CDirSpec(fileData.cFileName)));
return(lowerDir);
}
else
// Returning an empty directory
return(lowerDir);
#else
_find_t fileInfo;
bDirFound = !_dos_findfirst(searchPath.GetPath(), _A_SUBDIR | _A_ALL, &fileInfo);
// As long a something is found, but is not a good one, keep searching
// ... Ignore non-subdirectories and subdirectories starting with a full steop
while( (bDirFound) &&
( !(fileInfo.attrib & _A_SUBDIR) || (*fileInfo.name == '.') ) )
bDirFound = !_dos_findnext(&fileInfo);
if (bDirFound)
{
lowerDir = *this;
VERIFY(lowerDir.AppendDirectory(CDirSpec(fileInfo.name)));
return(lowerDir);
}
else
// Returning an empty directory
return(lowerDir);
#endif
}
BOOL CDirSpec::RemoveAllFiles(BOOL bAlsoRemoveReadOnly /* = FALSE */) const
// --- In : bAlsoRemoveReadOnly : Whether to remove all the files,
// even when they are read only (TRUE) or not (FALSE)
// --- Out :
// --- Returns : Whether all the removals succeeded
// --- Effect : Removes all the files of this directory
{
CPathSpec filePath;
VERIFY(filePath.SetPath(*this, CFileSpec(TEXT("*.*"))));
BOOL bFileFound(TRUE);
#ifdef WIN32
WIN32_FIND_DATA fileData;
HANDLE hFindFile = FindFirstFile(filePath.GetPath(), &fileData);
// As long a something is found, but is not a good one, keep searching
// ... Ignore non-subdirectories and subdirectories starting with a full steop
if(hFindFile != INVALID_HANDLE_VALUE)
{
while(bFileFound)
{
if (fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
bFileFound = FindNextFile(hFindFile, &fileData);
continue;
}
VERIFY(filePath.SetFileName(fileData.cFileName));
// If the file is Read/only and it is allowed to remove it, try so
if (fileData.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
{
if (bAlsoRemoveReadOnly)
{
if (!SetFileAttributes(filePath.GetPath(), fileData.dwFileAttributes & ~FILE_ATTRIBUTE_READONLY))
{
TRACE(TEXT("CDirSpec::RemoveAllFiles : Could not change the Read/Only attribute of file %s\n"),
filePath.GetPath());
::FindClose(hFindFile);
return FALSE;
}
}
else
{
TRACE(TEXT("CDirSpec::RemoveAllFiles : Could not remove the file %s, because it is Read/Only\n"),
filePath.GetPath());
::FindClose(hFindFile);
return FALSE;
}
}
if (!DeleteFile(filePath.GetPath()))
{
TRACE(TEXT("CDirSpec::RemoveAllFiles : Could not remove the file %s\n"), filePath.GetPath());
::FindClose(hFindFile);
return FALSE;
}
bFileFound = FindNextFile(hFindFile, &fileData);
} //while
::FindClose(hFindFile);
} // if(INVALID_HANDLE_VALUE)
#else
_find_t fileInfo;
VERIFY(filePath.SetPath(*this, CFileSpec(TEXT("*.*"))));
bFileFound = !_dos_findfirst(filePath.GetPath(), _A_ALL, &fileInfo);
while(bFileFound)
{
VERIFY(filePath.SetFileName(fileInfo.name));
// If the file is Read/only and it is allowed to remove it, try so
if (fileInfo.attrib & _A_RDONLY)
{
if (bAlsoRemoveReadOnly)
{
if (_dos_setfileattr(filePath.GetPath(), fileInfo.attrib & ~_A_RDONLY) != 0)
{
TRACE(TEXT("CDirSpec::RemoveAllFiles : Could not change the Read/Only attribute of file %s\n"),
filePath.GetPath());
return FALSE;
}
}
else
{
TRACE(TEXT("CDirSpec::RemoveAllFiles : Could not remove the file %s, because it is Read/Only\n"),
filePath.GetPath());
return FALSE;
}
}
if (remove(filePath.GetPath()) != 0)
{
TRACE(TEXT("CDirSpec::RemoveAllFiles : Could not remove the file %s\n"), filePath.GetPath());
return FALSE;
}
bFileFound = !_dos_findnext(&fileInfo);
}
#endif
return TRUE;
}
// private:
// Message handlers ---------------------------------------------------------
// ==========================================================================